home *** CD-ROM | disk | FTP | other *** search
- ; ------------------------------------
- ; Module for PCX.PAS and PCX.CPP
- ; Copyright (c) 1994 by Peter Donnelly
- ; ------------------------------------
-
- ; To compile for Pascal, put "/dpascal" on the TASM command line.
-
- ; To compile for C++, change the .MODEL definition to match your program's
- ; memory model. Then run TASM with the "/mx" switch on the command line.
-
- IFDEF PASCAL
- .MODEL TPASCAL
- ELSE
- .MODEL LARGE, C ; can be COMPACT, LARGE, or HUGE
- ENDIF
-
- .DATA
- extrn DataLength: word
- extrn Scratch: dword
- extrn Plane: word
- extrn VideoOffs: word
- extrn VideoSeg: word
- extrn Margin: word
- extrn ScreenWidth: word
- extrn LineEnd: word
- extrn RepeatCount: byte
- extrn ColumnCount: word
- extrn BytesPerLine: word
- .CODE
- PUBLIC Decode16
- PUBLIC Decode256
- LOCALS
-
- ; ----------------------------- 16-COLOR FILES ---------------------------
-
- Decode16 PROC
-
- ; Main use of registers:
-
- ; AL data byte to be written to video
- ; AH data bytes per scan line
- ; BX end of input buffer
- ; CL number of times data byte is to be written
- ; DL current column in scan line
- ; ES output segment
- ; DI index into output buffer
- ; SI index into input buffer
- ; BP current color plane
-
- push si ; save C register variables
- push di ; ditto
- push bp
-
- ; The first section is initialization done on each run through the
- ; input buffer.
-
- @@startproc:
- mov bp, Plane ; plane in BP
- mov di, VideoOffs ; index into video segment
- mov ah, byte ptr BytesPerLine ; line length in AH
- mov dx, ColumnCount ; column counter
- mov bx, DataLength ; no. of bytes to read
- xor cx, cx ; clean up CX for loop counter
- mov cl, RepeatCount ; count in CX
- les si, Scratch ; index into input buffer in SI
- ; ES not significant here - we don't use LDS because we want to
- ; preserve DS
- ; We have to adjust datalength for comparison with SI. Pascal pointers
- ; are normalized, but the offset can still be 0 or 8.
- mov es, VideoSeg ; video display segment
- add bx, si
- cld ; clear DF for stosb
- cmp cl, 0 ; was last byte a count?
- jne @@multi_data ; yes, so next is data
- jmp short @@getbyte ; no, so find out what next is
-
- ; The data in the .PCX file is organized by color plane, by line; that is,
- ; all the data for plane 0 for line 1, then for plane 1, line 1, etc.
- ; Writing the data to display memory is just a matter of masking out the
- ; other planes while one plane is being written to. This is done with the
- ; map mask register in the sequencer. All the other weird and wonderful
- ; registers in the EGA/VGA do just fine with their default settings, thank
- ; goodness.
-
- @@writebyte:
- stosb ; AL into ES:DI, inc DI
- inc dl ; increment column
- cmp dl, ah ; reached end of scanline?
- je @@doneline ; yes
- loop @@writebyte ; no, do another
- jmp short @@getbyte ; or get more data
- @@doneline:
- shl bp, 1 ; shift to next plane
- cmp bp, 8 ; done 4 planes?
- jle @@setindex ; no
- mov bp, 1 ; yes, reset plane to 1
- add di, Margin ; skip to start of next scanline
- mov dx, ScreenWidth
- add LineEnd, dx
- jmp short @@setplane
- @@setindex:
- sub di, dx ; reset index to start of same line
- @@setplane:
- push ax ; save AX
- cli ; no interrupts
- mov ax, bp ; plane is 1, 2, 4, or 8
- mov dx, 3C5h ; sequencer data register
- out dx, al ; mask out 3 planes
- sti ; enable interrupts
- pop ax ; restore AX
- xor dx, dx ; reset column count
- loop @@writebyte ; do it again, or fetch more data
-
- ; --- Loop through input buffer
-
- ; Here's how the data compression system works. Each byte is either image
- ; data or a count byte that tells how often the next byte is to be
- ; repeated. The byte is image data if it follows a count byte, or if
- ; either of the top 2 bits is clear. Otherwise it is a count byte, with
- ; the count derived from the lower 6 bits.
-
- @@getbyte: ; last byte was not a count
- cmp si, bx ; end of input buffer?
- je @@exit ; yes, quit
- push ds ; save program data
- push si
- lds si, Scratch ; input segment into DS
- pop si
- lodsb ; get a byte from DS:SI into AL, increment SI
- pop ds ; restore program data
- cmp al, 192 ; test high bits
- jb @@one_data ; not set, it's data to be written once
- ; It's a count byte:
- xor al, 192 ; get count from 6 low bits
- mov cl, al ; store repeat count
- cmp si, bx ; end of input buffer?
- je @@exit ; yes, quit
- @@multi_data:
- push ds ; save program data
- push si
- lds si, Scratch ; segment of input buffer into DS
- pop si
- lodsb ; get a byte from DS:SI into AL, increment SI
- pop ds ; restore program data
- jmp @@writebyte ; write it CL times
- @@one_data:
- mov cl, 1 ; write byte once
- jmp @@writebyte
-
- ; --- Finished with buffer ---
-
- @@exit:
- mov Plane, bp ; save status for next run thru buffer
- mov RepeatCount, cl
- mov ColumnCount, dx
- mov VideoOffs, di
- pop bp
- pop di ; restore any C register variables
- pop si
- ret
-
- Decode16 ENDP
-
- ; ------------------------- 256-COLOR VGA FILES ---------------------------
-
- Decode256 PROC
-
- ; Main use of registers:
-
- ; AL data byte to be written to video
- ; BX end of input buffer
- ; CL number of times data byte is to be written
- ; DX temporary storage of EndOfLine
- ; ES segment of output buffer
- ; DI index into output buffer
- ; SI index into input buffer
-
- push si ; save C register variables
- push di ; ditto
- push bp
-
- les si, Scratch ; index into input buffer in SI
- ; ES not used here - we don't use LDS because we want to preserve DS
- mov bx, DataLength ; end of input buffer
- add bx, si ; adjust datalength - SI may not be 0
- mov es, VideoSeg ; base address of output window
- mov di, VideoOffs ; index into window
- xor cx, cx ; clean up loop counter
- mov cl, RepeatCount ; restore count from last byte
- cld ; clear DF
- cmp cl, 0 ; was last byte a count?
- jne @@multi_data ; yes, so next is data
-
- ; --- Loop through input buffer ---
-
- @@getbyte: ; last byte was not a count
- cmp di, LineEnd ; reached end of line?
- jb @@NoLineEnd ; no
- add di, Margin
- mov dx, ScreenWidth
- add LineEnd, dx
- @@NoLineEnd:
- cmp si, bx ; end of input buffer?
- je @@exit ; yes, quit
- push ds ; save Pascal's data segment
- push si ; Get segment of input buffer into DS
- lds si, Scratch ; while preserving SI
- pop si
- lodsb ; get byte from DS:SI into AL, increment SI
- pop ds ; restore program data
- cmp al, 192 ; test high bits
- jb @@one_data ; not set, not a count
- ; It's a count byte
- xor al, 192 ; get count from 6 low bits
- mov cl, al ; store repeat count
- cmp si, bx ; end of input buffer?
- je @@exit ; yes, quit
- @@multi_data:
- push ds ; save program data
- push si
- lds si, Scratch
- pop si
- lodsb ; get byte from DS:SI into AL, increment SI
- pop ds ; restore program data
- rep stosb ; write byte CX times
- jmp @@getbyte
- @@one_data:
- stosb ; byte into video
- jmp @@getbyte
-
- ; --- Finished with buffer
- @@exit:
- mov VideoOffs, di ; save status for next run thru buffer
- mov RepeatCount, cl
- pop bp
- pop di ; restore any C register variables
- pop si
- ret
-
- Decode256 ENDP
-
- END
-
-